package storage

import (
	"fmt"
	"sync"
)

type IK interface {
	float32 | float64 | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | string
}

type IKComparator[value IK] struct {
	eval value
}

func NewIKComparator[V IK](val V) *IKComparator[V] {
	return &IKComparator[V]{eval: val}
}

func (i *IKComparator[value]) GT(val interface{}) bool {
	return i.eval > val.(value)
}

func (i *IKComparator[value]) GTE(val interface{}) bool {
	return i.eval >= val.(value)
}

func (i *IKComparator[value]) LT(val interface{}) bool {
	return i.eval < val.(value)
}

func (i *IKComparator[value]) LTE(val interface{}) bool {
	return i.eval <= val.(value)
}

func (i *IKComparator[value]) EQ(val interface{}) bool {
	return i.eval == val.(value)
}

func (i *IKComparator[value]) NE(val interface{}) bool {
	return i.eval != val.(value)
}

type Eraser interface {
	delete(item *Item)
}

type Item struct {
	data any
	leaf map[string]Eraser
}

func NewItem(data any) *Item {
	return &Item{data: data, leaf: map[string]Eraser{}}
}

func (i *Item) Value() any { return i.data }

type leafy[key IK] struct {
	Bp *BpNode[key]

	elements []*Item
}

func (l *leafy[key]) delete(element *Item) {
	if len(l.elements) == 1 {
		l.Bp.sharding.delete(l.Bp)
	} else {
		for i := 0; i < len(l.elements); i++ {
			if l.elements[i] == element {
				l.elements = append(l.elements[:i], l.elements[i:]...)
			}
		}
	}
}

func (l *leafy[key]) append(element *Item) {
	element.leaf[l.Bp.index] = l.Bp
	l.elements = append(l.elements, element)
}

type BpNode[key IK] struct {
	key   key
	layer uint8
	index string

	up   *BpNode[key]
	down *BpNode[key]

	prev *BpNode[key]
	next *BpNode[key]

	leafage  *leafy[key]
	sharding *Sharding[key]
}

func (b *BpNode[key]) delete(item *Item) {
	b.leafage.delete(item)
}

type Sharding[key IK] struct {
	cap uint8
	len uint8

	lock     sync.Mutex
	headLock *sync.Mutex
	tailLock *sync.Mutex

	head *BpNode[key]
	tail *BpNode[key]
}

func (s *Sharding[key]) split() {
	if s.len <= s.cap {
		// 分片未溢出
		return
	}

	sp := &Sharding[key]{
		cap:      s.cap,
		tail:     s.tail,
		headLock: s.tailLock,
	}

	for s.len > s.cap/2+1 {
		s.len--
		sp.len++
		sp.head = s.tail
		sp.head.sharding = sp
		s.tail = sp.head.prev
	}

	if sp.tail.next == nil {
		sp.tailLock = new(sync.Mutex)
	} else {
		sp.tailLock = sp.tail.next.sharding.headLock
	}

	up := &BpNode[key]{
		down: sp.head,

		key:   sp.head.key,
		index: sp.head.index,
		layer: sp.head.layer + 1,

		leafage: sp.head.leafage,
	}

	sp.head.up = up
	if s.head.up == nil {
		s.head.up = &BpNode[key]{
			down:  s.head,
			key:   s.head.key,
			index: s.head.index,
			layer: s.head.layer + 1,

			leafage: s.head.leafage,
		}
		s.head.up.sharding = &Sharding[key]{
			len:      1,
			cap:      s.cap,
			head:     s.head.up,
			tail:     s.head.up,
			tailLock: new(sync.Mutex),
		}
	}
	s.head.up.sharding.insert(s.head.up, up)
}

func (s *Sharding[key]) delete(knot *BpNode[key]) {
	s.lock.Lock()
	defer s.lock.Unlock()

	if knot == s.head {
		s.headLock.Lock()
		defer s.headLock.Unlock()
	} else if knot == s.tail {
		s.tailLock.Lock()
		defer s.tailLock.Unlock()
	}

	s.len--
	if s.head == s.tail && knot == s.head {
		for tn := knot.up; tn != nil; tn = tn.up {
			tn.sharding.delete(tn)
		}
	} else if knot == s.tail {
		s.tail = knot.prev
	} else if knot == s.head {
		s.head = knot.next
		s.head.up = knot.up
		s.head.up.down = knot.next
		for tn := knot.up; tn != nil; tn = tn.up {
			tn.key = s.head.key
			tn.leafage = s.head.leafage
		}
	}

	if knot.next != nil {
		knot.prev.next = knot.next
		knot.next.prev = knot.prev
	} else {
		knot.prev.next = nil
	}

	knot.next = nil
	knot.prev = nil
}

func (s *Sharding[key]) push(tie *BpNode[key]) {
	s.len++

	head := s.head
	for top := head.up; top != nil; top = top.up {
		top.key = tie.key
		top.leafage = tie.leafage
	}

	if head.up != nil {
		tie.up = head.up
		head.up.down = tie
	}
	s.head = tie
	head.up = nil
	tie.sharding = s

	head.prev = tie
	tie.next = head
}

func (s *Sharding[key]) insert(knot *BpNode[key], tie *BpNode[key]) {
	s.lock.Lock()
	defer s.lock.Unlock()

	if knot == s.tail {
		s.tailLock.Lock()
		defer s.tailLock.Unlock()

		// 在分片尾部插入节点
		if s.len >= s.cap && knot.next != nil && knot.next.sharding.len < knot.next.sharding.cap {
			// 当前分片满了 并且 右边节点存在 并且 右边节点分片未满
			knot.next.sharding.push(tie)
			knot.next = tie
			tie.prev = knot
			return
		} else {
			s.len++
			s.tail = tie
			tie.sharding = s
		}
	} else {
		s.len++
		tie.sharding = s
	}

	temp := knot.next

	knot.next = tie
	tie.prev = knot

	if temp != nil {
		temp.prev = tie
		tie.next = temp
	}

	s.split() // 检查分裂
}

type SkipTable[key IK] struct {
	*BpNode[key]
	tail *BpNode[key]
}

func NewSkipTable[key IK](name string, cap uint8) *SkipTable[key] {
	root := &BpNode[key]{index: name}
	root.sharding = &Sharding[key]{
		len:      1,
		cap:      cap,
		head:     root,
		tail:     root,
		tailLock: new(sync.Mutex),
	}
	return &SkipTable[key]{BpNode: root, tail: root}
}

func (s *SkipTable[key]) search(k key) (bp *BpNode[key]) {
	for bp = s.BpNode; ; {
		if bp.next != nil {
			if bp.next.key <= k {
				bp = bp.next
				continue
			}
		}
		if bp.down == nil {
			return bp
		}
		bp = bp.down
	}
}

func (s *SkipTable[key]) Del(k key) bool {
	bp := s.search(k)
	if bp.prev != nil && bp.key == k {
		bp.sharding.delete(bp)
		for i := range bp.leafage.elements {
			for k, e := range bp.leafage.elements[i].leaf {
				if k == s.index {
					continue
				}
				e.delete(bp.leafage.elements[i])
			}
		}
		return true
	} else {
		return false
	}
}

func (s *SkipTable[key]) Set(k key, element *Item) {
	bp := s.search(k)
	if bp.prev != nil && bp.key == k {
		bp.leafage.append(element)
	} else {
		leafage := new(leafy[key])
		leafage.Bp = &BpNode[key]{
			key:   k,
			layer: bp.layer,
			index: bp.index,

			leafage: leafage,
		}
		if bp == s.tail {
			s.tail = leafage.Bp
		}
		leafage.append(element)
		bp.sharding.insert(bp, leafage.Bp)
	}

	// 检测索引层级增加
	for s.BpNode.up != nil {
		s.BpNode = s.BpNode.up
	}
}

func (s *SkipTable[key]) Get(k key) (elements []*Item, ok bool) {
	bp := s.search(k)
	if bp.prev != nil && bp.key == k {
		return bp.leafage.elements, true
	} else {
		return elements, false
	}
}

func out[key IK](bp *BpNode[key]) *BpNode[key] {
	if bp.down == nil {
		if bp.up == nil {
			fmt.Print(fmt.Sprintf("[nil]%v[nil]-> ", bp.key))
		} else {
			fmt.Print(fmt.Sprintf("[%v]%v[nil]-> ", bp.up.key, bp.key))
		}

	} else {
		if bp.up == nil {
			fmt.Print(fmt.Sprintf("[nil]%v[%v] -> ", bp.key, bp.down.key))
		} else {
			fmt.Print(fmt.Sprintf("[%v]%v[%v] -> ", bp.up.key, bp.key, bp.down.key))
		}
	}

	if bp.next != nil {
		out(bp.next)
	}
	return bp
}

func FmtPrintSkipTableIndex[key IK](table *SkipTable[key]) {
	for root := out(table.BpNode); root.down != nil; root = out(root) {
		root = root.down
		fmt.Println()
	}
	fmt.Println()
}

type (
	// Comparator 比较器
	Comparator interface {
		GT(val interface{}) bool  // 大于比较
		GTE(val interface{}) bool // 大于等于比较
		LT(val interface{}) bool  // 小于比较
		LTE(val interface{}) bool // 小于等于比较
		EQ(val interface{}) bool  // 等于比较
		NE(val interface{}) bool  // 不等于比较
	}
	// Field2Comparator 获取字段比较器
	Field2Comparator interface {
		GetFieldComparator(field string) Comparator
	}
)

func PreCompare(where map[string]interface{}) func(c Field2Comparator) bool {
	exec := make([]func(c Field2Comparator) bool, 0)
	for act, operation := range where {
		switch act {
		case "$or":
			eval := make([]func(c Field2Comparator) bool, 0)
			compares := operation.([]map[string]interface{})
			for idx := range compares {
				eval = append(eval, PreCompare(compares[idx]))
			}
			exec = append(exec, func(c Field2Comparator) bool {
				for idx := range exec {
					if exec[idx](c) {
						return true
					}
				}
				return false
			})
		case "$and":
			eval := make([]func(c Field2Comparator) bool, 0)
			compares := operation.([]map[string]interface{})
			for idx := range compares {
				eval = append(eval, PreCompare(compares[idx]))
			}
			exec = append(exec, func(c Field2Comparator) bool {
				for idx := range exec {
					if !exec[idx](c) {
						return false
					}
				}
				return true
			})
		default:
			if compare, ok := operation.(map[string]interface{}); ok {
				exec = append(exec, comparator(act, compare))
			} else {
				exec = append(exec, comparator(act, map[string]interface{}{"$eq": operation}))
			}
		}
	}
	return func(c Field2Comparator) (r bool) {
		for idx := range exec {
			if !exec[idx](c) {
				return false
			}
		}
		return true
	}
}

func comparator(field string, compare map[string]interface{}) func(c Field2Comparator) bool {
	exec := make([]func(c Field2Comparator) bool, 0)
	for sign, val := range compare {
		switch sign {
		case "$gt":
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).GT(val) })
		case "$gte":
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).GTE(val) })
		case "$lt":
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).LT(val) })
		case "$lte":
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).LTE(val) })
		case "$eq":
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).EQ(val) })
		case "$ne":
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).NE(val) })
		default:
			exec = append(exec, func(c Field2Comparator) bool { return c.GetFieldComparator(field).EQ(val) })
		}
	}
	return func(c Field2Comparator) (r bool) {
		for idx := range exec {
			if !exec[idx](c) {
				return false
			}
		}
		return true
	}
}

type (
	// Result 结果集
	Result interface {
		// Error 查询失败错误
		Error() error
		// Delete 删除查询结果
		Delete() uint64
		// Values 获取查询结果
		Values(int) ([]*Item, func())
		// Update 修改结果集数据
		Update(val map[string]interface{}, multi bool)
	}

	// Filter 过滤器
	Filter interface {
		Result
		// Where 条件查询
		Where(where map[string]interface{}) Result
	}
)

var SlicePool = sync.Pool{}

type ItemResult struct {
	limit  *int
	filter func(val *Item) bool
	values func(func(val *Item) bool, *[]*Item)
}

func (i *ItemResult) get() (slice []*Item) {
	v := SlicePool.Get()
	if v != nil {
		slice = v.([]*Item)[:0]
	} else {
		slice = make([]*Item, 0, 8)
	}
	return
}

func (i *ItemResult) Error() error {
	return nil
}

func (i *ItemResult) Delete() (num uint64) {
	slice := SlicePool.Get()
	defer SlicePool.Put(slice)
	results := slice.([]*Item)[:0]

	i.values(i.filter, &results)
	for _, item := range results {
		for _, eraser := range item.leaf {
			eraser.delete(item)
		}
		num++
	}
	return
}

func (i *ItemResult) Values(limit int) (values []*Item, recycle func()) {
	*i.limit = limit
	values = i.get()
	i.values(i.filter, &values)
	return values, func() { SlicePool.Put(values) }
}

func (i *ItemResult) Update(val map[string]interface{}, multi bool) {
	var (
		recycle  func()
		elements []*Item
	)
	if !multi {
		elements, recycle = i.Values(1)
	} else {
		elements, recycle = i.Values(-1)
	}
	defer recycle()
	for idx := range elements {
		elements[idx].Update(val)
	}
}

type ItemFilter struct {
	ItemResult
}

func (i *ItemFilter) Where(where map[string]interface{}) Result {
	compare := PreCompare(where)
	i.filter = func(val *Item) bool {
		return compare(val.data.(Field2Comparator))
	}
	return i
}

func (s *SkipTable[key]) GT(k key) Filter {
	limit := -1
	return &ItemFilter{
		ItemResult{
			filter: nil,
			limit:  &limit,
			values: func(where func(val *Item) bool, values *[]*Item) {
				bp := s.search(k)
				for n := bp.next; n != nil; n = n.next {
					for _, val := range n.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
				return
			},
		},
	}
}

func (s *SkipTable[key]) GTE(k key) Filter {
	limit := -1
	return &ItemFilter{
		ItemResult{
			filter: nil,
			limit:  &limit,
			values: func(where func(val *Item) bool, values *[]*Item) {
				bp := s.search(k)
				gn := func() *BpNode[key] {
					if bp.key == k {
						return bp
					} else {
						return bp.next
					}
				}
				for n := gn(); n != nil; n = n.next {
					for _, val := range n.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
				return
			},
		},
	}
}

func (s *SkipTable[key]) LT(k key) Filter {
	limit := -1
	return &ItemFilter{
		ItemResult{
			filter: nil,
			limit:  &limit,
			values: func(where func(val *Item) bool, values *[]*Item) {
				bp := s.search(k)
				gn := func() *BpNode[key] {
					if bp.key < k {
						return bp
					} else {
						return bp.prev

					}
				}
				for n := gn(); n != nil; n = n.prev {
					if n.prev == nil {
						continue
					}
					for _, val := range n.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
				return
			},
		},
	}
}

func (s *SkipTable[key]) LTE(k key) Filter {
	limit := -1
	return &ItemFilter{
		ItemResult{
			filter: nil,
			limit:  &limit,
			values: func(where func(val *Item) bool, values *[]*Item) {
				bp := s.search(k)
				for n := bp; n != nil; n = n.next {
					if n.prev == nil {
						continue
					}
					for _, val := range n.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
				return
			},
		},
	}
}

func (s *SkipTable[key]) EQ(k key) Filter {
	limit := -1
	return &ItemFilter{
		ItemResult{
			filter: nil,
			limit:  &limit,
			values: func(where func(val *Item) bool, values *[]*Item) {
				bp := s.search(k)
				if bp.key == k {
					for _, val := range bp.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
			},
		},
	}
}

func (s *SkipTable[key]) NE(k key) Filter {
	limit := -1
	return &ItemFilter{
		ItemResult{
			filter: nil,
			limit:  &limit,
			values: func(where func(val *Item) bool, values *[]*Item) {
				bp := s.search(k)
				// LT
				gn := func() *BpNode[key] {
					if bp.key < k {
						return bp
					} else {
						return bp.prev
					}
				}
				for n := gn(); n != nil; n = n.prev {
					if n.prev == nil {
						continue
					}
					for _, val := range n.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
				// GT
				for n := bp.next; n != nil; n = n.next {
					for _, val := range n.leafage.elements {
						if where == nil {
							*values = append(*values, val)
						} else {
							if where(val) {
								*values = append(*values, val)
							}
						}
						if limit != -1 && len(*values) >= limit {
							return
						}
					}
				}
				return
			},
		},
	}
}

func (s *SkipTable[key]) Sort(reverse bool) Result {
	limit := -1
	return &ItemResult{
		filter: nil,
		limit:  &limit,
		values: func(where func(val *Item) bool, values *[]*Item) {
			gn := func() *BpNode[key] {
				if reverse {
					return s.tail
				} else {
					n := s.BpNode
					for n.down != nil {
						n = n.down
					}
					return n.next
				}
			}
			next := func(n *BpNode[key]) *BpNode[key] {
				if !reverse {
					return n.next
				} else {
					if n.prev.prev == nil {
						return nil
					}
					return n.prev
				}
			}
			for n := gn(); n != nil; n = next(n) {
				for _, val := range n.leafage.elements {
					if where == nil {
						*values = append(*values, val)
					} else {
						if where(val) {
							*values = append(*values, val)
						}
					}
					if limit != -1 && len(*values) >= limit {
						return
					}
				}
			}
		},
	}
}
